import os
from ctypes import *
import time

lib_pthread = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libpthread-2.23.so')
libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')


def lib_c_mmap(mmap_size_in_byte):
    # 使用clib的mmap功能申请一块内存并返回地址
    # 获得mmap所在的lib库名称
    # ./x86_64-linux-gnu/libc.so  mmap所在so
    # root@localhost:/usr/lib# nm -D /lib/x86_64-linux-gnu/libc.so.6|grep mmap
    # 0000000000101680 W mmap
    # 0000000000101680 W mmap64
    # / *映射一片内存 * /
    # void * p = mmap(0, // 让系统指定映射内存的首地址(虚拟地址)
    # 4, // 映射4bytes的空间，其实会映射一页内存
    # PROT_READ | PROT_WRITE, // 权限，有读写权限
    # MAP_PRIVATE | MAP_ANONYMOUS, / *MAP_ANONYMOUS: 匿名映射，当映射到内存时，只能使用匿名映射。MAP_SHARED和MAP_PRIVATE必选其一。 * /
    # 0, // 文件描述符，用于映射到文件，内存映射中会忽略
    # 0); // 文件偏移量，用于文件，内存映射也会忽略
    # if (p == MAP_FAILED){  失败返回-1 #define MAP_FAILED	((void *) -1)
    # perror("映射失败");
    # exit(-1);
    # }
    PROT_READ = 0x1
    PROT_WRITE = 0x2
    PROT_EXEC = 0x4
    PROT_NONE = 0x0
    PROT = PROT_READ | PROT_WRITE | PROT_EXEC

    MAP_PRIVATE = 0x02
    MAP_ANONYMOUS = 0x20
    MAP_TYPE = 0x02 | 0x20

    # 使用Mmap分配内存
    # // 申请内存
    # int * arr = static_cast < int * > (mmap(
    #     NULL, // 分配的首地址
    #     getpagesize(), // 分配内存大小(必须是页的整数倍, 32位1页 = 4k)
    # PROT_READ | PROT_WRITE, // 映射区域保护权限：读 | 写
    # MAP_ANON | MAP_SHARED, // 匿名映射(不涉及文件io), 后面两个参数忽略
    # 0, // 要映射到内存中的文件描述符
    # 0 // 文件映射的偏移量，通常设置为0，必须是页的整数倍
    # ));

    # 调用必须制定输入输出类型
    libc.mmap.argtypes = [c_int, c_int, c_int, c_int, c_int, c_int]
    libc.mmap.restype = c_void_p
    addr = libc.mmap(c_int(0), c_int(mmap_size_in_byte), PROT, c_int(MAP_TYPE), c_int(0), c_int(0))
    return addr


def lib_c_memcpy(dst, src, size):
    # 拷贝一段内存到目标地址上
    # void *memcpy(void *dest, const void *src, size_t count)  拷贝函数
    # libc.memcpy.argtypes = [c_void_p, c_void_p, c_size_t]
    libc.memcpy.restype = c_void_p
    ret = libc.memcpy(dst, src, size)
    return ret


def lib_pthread_create(tid=0, pthread_attr_t=None, fun=None, input_args=None):
    # ./x86_64-linux-gnu/bits/pthreadtypes.h:60:typedef unsigned long int pthread_t;
    # gdb 内部设置intel set disassembly-flavor intel
    # extern int pthread_create (
    # pthread_t *__restrict __newthread,
    # const pthread_attr_t *__restrict __attr,
    # void *(*__start_routine) (void *),
    # void *__restrict __arg) __THROWNL __nonnull ((1, 3));

    # print(dir(lib))
    # print(lib.__doc__)
    # print(lib.__module__)
    # print(lib.__class__)
    # err = pthread_create(&ntid, NULL, thr_fn, NULL);
    # extern int pthread_create (
    # pthread_t *__restrict __newthread,
    # const pthread_attr_t *__restrict __attr,
    # void *(*__start_routine) (void *),
    # void *__restrict __arg) __THROWNL __nonnull ((1, 3));

    if tid != 0:
        # lib_pthread.pthread_create.argtypes = [c_ulong,None,c_void_p,]
        lib_pthread.pthread_create.restype = c_int
        ret = lib_pthread.pthread_create(tid, pthread_attr_t, fun, input_args)
        return ret


def lib_pthread_join(tid=0):
    # int pthread_join(pthread_t thread, void **value_ptr);
    # thread：等待退出线程的线程号。
    # value_ptr：退出线程的返回值。
    if tid != 0:
        ret = lib_pthread.pthread_join(tid, None)
        return ret


def build_nasm(file):
    if file != '':
        ret = os.sysconf(r'nasm -d ' + file + ' -o ' + file + r'.bin')
        return ret
    else:
        return
